﻿using System.IO;
using NUnit.Framework;
using UseCaseManager.BO;
using UseCaseManager.Logic;
using UseCaseManager.Test.BO;

namespace UseCaseManager.Test.Logic
{
    [TestFixture]
    public class TestWriteDocuments
    {
        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            //Clear and Load Class Defs
            TestUtils.TestFixtureSetup();
        }

        [SetUp]
        public virtual void SetupTest()
        {
            //-------------------------------------------------------------------------------------
            // You can choose here whether to run against a database or whether to use an in-memory
            // database for all the tests, which runs quickly. It doesn't however check that
            // your database has the correct structure, which is partly the purpose of these tests.
            // The generated tests do already use an in-memory database where possible.
            // In your custom tests, you can set them to use an in-memory database by copying the
            // line to the first line of your test.
            //-------------------------------------------------------------------------------------
            //BORegistry.DataAccessor = new DataAccessorDB();
            //Sets up In memory, clears business object manager
            TestUtils.TestSetup();
        }

        [Test]
        public void Test_WriteXmlFile()
        {
            //---------------Set up test pack-------------------
            Project project = CreateValidProject();
            const string fileName = @"TestWriteToXmlFile.xml";
            if (File.Exists(fileName)) File.Delete(fileName);
            //---------------Assert Precondition----------------
            AssertFileDoesNotExist(fileName);
            //---------------Execute Test ----------------------
            WriteDocuments.WriteToXmlFile(project, fileName);
            //---------------Test Result -----------------------
            AssertFileHasBeenCreated(fileName);
        }

        [Test ]
        public void Test_WriteToWordDocument()
        {
            //---------------Set up test -----------------------
            Project project = CreateValidProject();
            const string xmlFileName = @"TestWriteToWordDoc.xml";
            const string xslFileName = @"ProjectToWordTemplate.xsl";
            string xslFilePath = Path.Combine("Templates", xslFileName);
            const string docFileName = @"TestWriteProjectToWordDocument.doc";
            if (File.Exists(docFileName)) File.Delete(docFileName);
            WriteDocuments.WriteToXmlFile(project, xmlFileName);
            //---------------Assert pre conditions -------------
            Assert.IsTrue(File.Exists(xslFilePath),
                          "The file : " + xslFilePath + " should be in the current directory");
            AssertFileDoesNotExist(docFileName);
            //---------------Execute Test ----------------------
            WriteDocuments.WriteProjectToWordDocument(xmlFileName, xslFilePath, docFileName);
            //---------------Test Result -----------------------
            AssertFileHasBeenCreated(docFileName);
        }

        //TODO: Refactor this functionality to allow testing on build server?
        [Test, Ignore("Fails on build server possibly due to server not supporting word2007")]
        public void Test_WriteRequirementsToWordDocument()
        {
            //---------------Set up test -----------------------
            const string projectDocName = @"TestWriteProjectToWordDocument.doc";
            if (File.Exists(projectDocName)) File.Delete(projectDocName);
            CreateValidProjectDocument(projectDocName);
            const string requirementsDocName = @"RequirementsDocumentTemplate.docx";
            string requirementsDocPath = Path.Combine("Templates", requirementsDocName);
            const string generatedDocName = @"TestWriteRequirementsToWordDocument.docx";
            const string insertionPointBookmark = @"UseCases";
            if (File.Exists(generatedDocName)) File.Delete(generatedDocName);
            //---------------Assert pre conditions -------------
            Assert.IsTrue(File.Exists(requirementsDocPath), "The file : " + requirementsDocPath + " should be in the current directory");
            AssertFileDoesNotExist(generatedDocName);
            //---------------Execute Test ----------------------
            WriteDocuments.WriteRequirementsToWordDocument(projectDocName, requirementsDocPath, generatedDocName, insertionPointBookmark);
            //---------------Test Result -----------------------
            AssertFileHasBeenCreated(generatedDocName);
        }

        private static void CreateValidProjectDocument(string docName)
        {
            Project project = CreateValidProject();
            const string xmlFileName = @"TestWriteToWordDoc.xml";
            const string xslFileName = @"ProjectToWordTemplate.xsl";
            string xslFilePath = Path.Combine("Templates", xslFileName);
            WriteDocuments.WriteToXmlFile(project, xmlFileName);
            WriteDocuments.WriteProjectToWordDocument(xmlFileName, xslFilePath, docName);
        }

        /// <summary>
        /// Sets up a hierarchy of objects, 1 per relevant level, with composite relationships
        /// </summary>
        private static Project CreateValidProject()
        {
            //---------------Set up test -----------------------
            Project project = TestUtilsProject.CreateUnsavedValidProject();
            Package package = TestUtilsPackage.CreateUnsavedValidPackage();
            UseCase useCase = TestUtilsUseCase.CreateUnsavedValidUseCase();
            UseCaseStep useCaseStep = TestUtilsUseCaseStep.CreateUnsavedValidUseCaseStep();
            UseCaseStep useCaseStep2 = TestUtilsUseCaseStep.CreateUnsavedValidUseCaseStep();
            useCase.UseCaseSteps.Add(useCaseStep2);
            useCase.UseCaseSteps.Add(useCaseStep);
            package.UseCases.Add(useCase);
            project.Packages.Add(package);
            return project;
        }

        private static void AssertFileHasBeenCreated(string fullFileName)
        {
            Assert.IsTrue(File.Exists(fullFileName), "The file : " + fullFileName + " should have been created");
        }

        private static void AssertFileDoesNotExist(string fullFileName)
        {
            Assert.IsFalse(File.Exists(fullFileName), "The file : " + fullFileName + " should not exist");
        }
    }
}
